🎖️GitЯра🎖️
Commit 613dee91bf88cd5a9cfdbddc176db094042c6f3e
Parents : b5dd6ff
Author : James Rich <james.a.rich@gmail.com>
Date : 2026-06-13T07:27:56-05:00
fix(database): use a single connection for in-memory test databases
configureCommon() applied setMultipleConnectionPool(maxNumOfReaders = 4)
to every database, including the in-memory ones used by tests. A read on
a pooled reader connection can observe a snapshot older than the latest
write on the writer connection, so a read immediately after a write may
return stale rows.
DeviceLinkRepositoryImplTest.reconcilePrunesShortCodesNoLongerInCatalog
read [a, b] (the pre-prune state) instead of [a] after a deleteNotIn —
passing locally but flaking on CI depending on connection-assignment
timing (failed shard-core on #5738; the identical code passed on #5780).
In-memory builders now pass multiConnection = false so reads serialize
behind writes on one connection. Production/file databases keep the
multi-reader pool.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Changes
4 files changed, 17 insertions(+), 8 deletions(-)
Diff
diff --git a/core/database/src/androidMain/kotlin/org/meshtastic/core/database/DatabaseBuilder.kt b/core/database/src/androidMain/kotlin/org/meshtastic/core/database/DatabaseBuilder.kt
index 8e9fbbac23..e5e97fcfb2 100644
--- a/core/database/src/androidMain/kotlin/org/meshtastic/core/database/DatabaseBuilder.kt
+++ b/core/database/src/androidMain/kotlin/org/meshtastic/core/database/DatabaseBuilder.kt
@@ -45,7 +45,7 @@ actual fun getDatabaseBuilder(dbName: String): RoomDatabase.Builder<MeshtasticDa
/** Returns a [RoomDatabase.Builder] configured for an in-memory Android database. */
actual fun getInMemoryDatabaseBuilder(): RoomDatabase.Builder<MeshtasticDatabase> =
Room.inMemoryDatabaseBuilder<MeshtasticDatabase>(factory = { MeshtasticDatabaseConstructor.initialize() })
- .configureCommon()
+ .configureCommon(multiConnection = false)
.setDriver(BundledSQLiteDriver())
/** Returns the Android directory where database files are stored. */
diff --git a/core/database/src/commonMain/kotlin/org/meshtastic/core/database/MeshtasticDatabase.kt b/core/database/src/commonMain/kotlin/org/meshtastic/core/database/MeshtasticDatabase.kt
index bea88198d9..4baa33afb4 100644
--- a/core/database/src/commonMain/kotlin/org/meshtastic/core/database/MeshtasticDatabase.kt
+++ b/core/database/src/commonMain/kotlin/org/meshtastic/core/database/MeshtasticDatabase.kt
@@ -139,11 +139,20 @@ abstract class MeshtasticDatabase : RoomDatabase() {
abstract fun discoveryDao(): DiscoveryDao
companion object {
- /** Configures a [RoomDatabase.Builder] with standard settings for this project. */
- fun <T : RoomDatabase> RoomDatabase.Builder<T>.configureCommon(): RoomDatabase.Builder<T> =
- this.fallbackToDestructiveMigration(dropAllTables = false)
- .setMultipleConnectionPool(maxNumOfReaders = 4, maxNumOfWriters = 1)
- .setQueryCoroutineContext(ioDispatcher)
+ /**
+ * Configures a [RoomDatabase.Builder] with standard settings for this project.
+ *
+ * @param multiConnection opens a multi-reader connection pool for concurrent reads. Production/file databases
+ * want this. In-memory databases (tests) MUST pass `false`: a pooled reader connection can serve a snapshot
+ * older than the latest write on the writer connection, so a read immediately after a write may observe stale
+ * rows — making read-after-write assertions non-deterministically flaky (see `DeviceLinkRepositoryImplTest`).
+ * A single connection serializes reads behind writes.
+ */
+ fun <T : RoomDatabase> RoomDatabase.Builder<T>.configureCommon(
+ multiConnection: Boolean = true,
+ ): RoomDatabase.Builder<T> = this.fallbackToDestructiveMigration(dropAllTables = false)
+ .apply { if (multiConnection) setMultipleConnectionPool(maxNumOfReaders = 4, maxNumOfWriters = 1) }
+ .setQueryCoroutineContext(ioDispatcher)
}
}
diff --git a/core/database/src/iosMain/kotlin/org/meshtastic/core/database/DatabaseBuilder.kt b/core/database/src/iosMain/kotlin/org/meshtastic/core/database/DatabaseBuilder.kt
index 459c024eaa..6cecf57f15 100644
--- a/core/database/src/iosMain/kotlin/org/meshtastic/core/database/DatabaseBuilder.kt
+++ b/core/database/src/iosMain/kotlin/org/meshtastic/core/database/DatabaseBuilder.kt
@@ -51,7 +51,7 @@ actual fun getDatabaseBuilder(dbName: String): RoomDatabase.Builder<MeshtasticDa
/** Returns a [RoomDatabase.Builder] configured for an in-memory iOS database. */
actual fun getInMemoryDatabaseBuilder(): RoomDatabase.Builder<MeshtasticDatabase> =
Room.inMemoryDatabaseBuilder<MeshtasticDatabase>(factory = { MeshtasticDatabaseConstructor.initialize() })
- .configureCommon()
+ .configureCommon(multiConnection = false)
.setDriver(BundledSQLiteDriver())
/** Returns the iOS directory where database files are stored. */
diff --git a/core/database/src/jvmMain/kotlin/org/meshtastic/core/database/DatabaseBuilder.kt b/core/database/src/jvmMain/kotlin/org/meshtastic/core/database/DatabaseBuilder.kt
index 9686529d7b..50e84898d3 100644
--- a/core/database/src/jvmMain/kotlin/org/meshtastic/core/database/DatabaseBuilder.kt
+++ b/core/database/src/jvmMain/kotlin/org/meshtastic/core/database/DatabaseBuilder.kt
@@ -57,7 +57,7 @@ actual fun getDatabaseBuilder(dbName: String): RoomDatabase.Builder<MeshtasticDa
/** Returns a [RoomDatabase.Builder] configured for an in-memory JVM database. */
actual fun getInMemoryDatabaseBuilder(): RoomDatabase.Builder<MeshtasticDatabase> =
Room.inMemoryDatabaseBuilder<MeshtasticDatabase>(factory = { MeshtasticDatabaseConstructor.initialize() })
- .configureCommon()
+ .configureCommon(multiConnection = false)
.setDriver(BundledSQLiteDriver())
/** Returns the JVM/Desktop directory where database files are stored. */
Served by rngit 1.5.0 - Generated in 0.08s